package com.kaibes.web.request;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import com.kaibes.core.base.util.ArrayUtils;
import com.kaibes.web.filter.DoFilterInternal;
import com.kaibes.web.filter.FilterInternal;
import com.kaibes.web.filter.RequestFilterException;

@Component
@Order(4)
public class RequestBodyDoFilter implements DoFilterInternal, InitializingBean {

	@Value("${kaibes.web.request.max-request-size:-1}")
	private int maxRequestSize;
	private long maxRequestByte;
	
    @Autowired(required = false)
    private List<RequestBodyListener> requestBodyListeners;

    @Override
    public void doFilterInternal(FilterInternal filterInternal) throws ServletException, IOException {
        if (requestBodyListeners == null || requestBodyListeners.isEmpty() || filterInternal.getRequest().getContentType() == null) {
            return;
        }

        HttpServletRequest request = filterInternal.getRequest();
        byte[] body = null;
        for (RequestBodyListener listener : requestBodyListeners) {
            if (listener.supports(request)) {
                body = StreamUtils.copyToByteArray(request.getInputStream());
                break;
            }
        }

        if (body == null) {
            return;
        }

        if (body.length != 0) {
        	if (body.length > maxRequestByte) {
        		throw new RequestFilterException("请求失败，数据不能超过"+maxRequestSize+"MB");
        	}
            for (RequestBodyListener listener : requestBodyListeners) {
                if (listener.supports(request)) {
                    body = listener.doWithBody(filterInternal, body);
                    if (ArrayUtils.isEmpty(body)) {
                        break;
                    }
                }
            }
        }
        
        RequestBodyWrapper wrapper = new RequestBodyWrapper(request, body);
        if (body == null) {
            filterInternal.setBroken(true);
        }
        filterInternal.setRequest(wrapper);
        
    }
	
    @Override
	public void afterPropertiesSet() throws Exception {
    	if (maxRequestSize == -1) {
    		maxRequestByte = Long.MAX_VALUE;
    	} else {
    		maxRequestByte = maxRequestSize * 1024 * 1024;
    	}
    	if (requestBodyListeners != null) {
            Collections.sort(requestBodyListeners, (o1, o2) -> Integer.compare(o1.order(), o2.order()));
        }
	}

}
